package com.wpen.unit.core.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.wpen.unit.core.service.CommunityHandler;
import com.wpen.unit.core.service.NoticeHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.wpen.unit.core.ddo.JobAgentBindingDo;
import com.wpen.unit.core.ddo.JobRunningDo;
import com.wpen.unit.enums.ExecStatus;
import com.wpen.unit.infra.mybatis.job.po.AgentExec1LogPo;
import com.wpen.unit.infra.mybatis.job.po.AgentRegistryPo;
import com.wpen.unit.infra.mybatis.job.po.BatchExecLogPo;
import com.wpen.unit.infra.mybatis.job.po.JobExec1LogPo;
import com.wpen.unit.infra.mybatis.job.po.JobUndoPlanPo;
import com.wpen.unit.infra.mybatis.job.po.TaskInfoPo;
import com.wpen.unit.infra.mybatis.job.po.TaskPlanPo;
import com.wpen.unit.infra.repository.job.AgentExec1LogRepository;
import com.wpen.unit.infra.repository.job.BatchExecLogRepository;
import com.wpen.unit.infra.repository.job.JobExec1LogRepository;
import com.wpen.unit.infra.repository.job.JobUndoPlanRepository;
import com.wpen.unit.infra.repository.job.TaskPlanRepository;
import com.wpen.unit.utils.IdUtil;
import com.wpen.unit.web.WebVariables;
import com.wpen.unit.web.dto.ContextResponse;

/**
 *
 *
 * @author Wang Peng
 * @date 2022年12月18日
 * 
 */
@Service
public class CommunityHandlerImpl implements CommunityHandler {
	@Autowired
	private JobUndoPlanRepository jobUndoPlanRepository;
	@Autowired
	private JobExec1LogRepository jobExec1LogRepository;
	@Autowired
	private AgentExec1LogRepository agentExec1LogRepository;
	@Autowired
	private BatchExecLogRepository batchExecLogRepository;
	@Autowired
	private TaskPlanRepository taskPlanRepository;
	@Autowired
	private NoticeHelper noticeHelper;

	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void checkTaskFinished(Long batchLogId) {
		BatchExecLogPo batchExecLogPo = batchExecLogRepository.queryById(batchLogId);
		if (ExecStatus.Running.value().equals(batchExecLogPo.getExecStatus())) {
			BatchExecLogPo upBatchExecLogPo = new BatchExecLogPo();
			upBatchExecLogPo.setId(batchLogId);
			upBatchExecLogPo.setEndTime(new Date());
			upBatchExecLogPo.setExecStatus(ExecStatus.Finished.value());
			batchExecLogRepository.updateById(upBatchExecLogPo);

			List<TaskPlanPo> taskPlanPos = taskPlanRepository.queryListByBatchLogId(batchLogId);
			if (taskPlanPos != null && !taskPlanPos.isEmpty()) {
				List<Serializable> list = new ArrayList<>();
				Serializable[] ids = new Serializable[taskPlanPos.size()];
				taskPlanPos.forEach(item -> {
					list.add(item.getId());
				});
				taskPlanRepository.deleteByIds(list.toArray(ids));
			}
			// 通知
			noticeHelper.recordNotice(batchExecLogPo);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void updateAfterSendSocketTimeoutException(JobRunningDo jobRunningDo) {
		// 没有驱动成功，停止这个agent执行
		AgentExec1LogPo upAgentExec1Log = new AgentExec1LogPo();
		upAgentExec1Log.setId(jobRunningDo.getAgentId());
		upAgentExec1Log.setExecStatus(ExecStatus.Excption.value());
		upAgentExec1Log.setExecResult("发送调用指令失败，执行器调度任务回退，重新执行。");
		agentExec1LogRepository.updateById(upAgentExec1Log);
		JobUndoPlanPo upUndoPlanPo = new JobUndoPlanPo();
		upUndoPlanPo.setId(jobRunningDo.getJobLogId());
		upUndoPlanPo.setExecStatus(ExecStatus.Init.value());
		jobUndoPlanRepository.updateById(upUndoPlanPo);
		JobExec1LogPo upJobExec1LogPo = new JobExec1LogPo();
		upJobExec1LogPo.setId(jobRunningDo.getJobLogId());
		upJobExec1LogPo.setExecStatus(ExecStatus.Init.value());
		jobExec1LogRepository.updateById(upJobExec1LogPo);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public JobAgentBindingDo updateBeforeSend(JobUndoPlanPo jobUndoPlanPo, JobExec1LogPo jobExec1LogPo,
			AgentRegistryPo agentRegistryPo, TaskInfoPo taskInfoPo) {
		JobAgentBindingDo agentJobBindingDo = new JobAgentBindingDo();

		JobUndoPlanPo upUndoPlanPo = new JobUndoPlanPo();
		upUndoPlanPo.setId(jobUndoPlanPo.getId());
		upUndoPlanPo.setExecStatus(ExecStatus.Running.value());
		jobUndoPlanRepository.updateById(upUndoPlanPo);
		jobUndoPlanPo.setExecStatus(ExecStatus.Running.value());
		agentJobBindingDo.setJobUndoPlanPo(jobUndoPlanPo);

		JobExec1LogPo upJobExec1LogPo = new JobExec1LogPo();
		upJobExec1LogPo.setId(jobExec1LogPo.getId());
		upJobExec1LogPo.setExecStatus(ExecStatus.Running.value());
		jobExec1LogRepository.updateById(upJobExec1LogPo);
		jobExec1LogPo.setExecStatus(ExecStatus.Running.value());
		agentJobBindingDo.setJobExec1LogPo(jobExec1LogPo);

		AgentExec1LogPo agentExec1LogPo = new AgentExec1LogPo();
		agentExec1LogPo.setId(IdUtil.nextId());
		agentExec1LogPo.setTaskExecLogId(jobExec1LogPo.getTaskExecLogId());
		agentExec1LogPo.setJobExecLogId(jobExec1LogPo.getId());
		agentExec1LogPo.setTaskTriggerTime(jobExec1LogPo.getTaskTriggerTime());
		agentExec1LogPo.setExecDate(jobExec1LogPo.getExecDate());
		agentExec1LogPo.setAppMode(jobUndoPlanPo.getAppMode());
		agentExec1LogPo.setAppJarName(jobUndoPlanPo.getAppJarName());
		agentExec1LogPo.setAppRunMode(taskInfoPo.getAppRunMode());
		String startupCmd = taskInfoPo.getAppStartupCmd();
		agentExec1LogPo.setExecStartupCmd(startupCmd);
		agentExec1LogPo.setExecStatus(ExecStatus.Init.value());
		agentExec1LogPo.setExecErrorNum(0);
		agentExec1LogPo.setAgentIpv4(agentRegistryPo.getAgentIpv4());
		agentExec1LogPo.setStartupTime(new Date());
		agentExec1LogPo.setCreateTime(new Date());
		agentExec1LogRepository.insert(agentExec1LogPo);
		agentJobBindingDo.setAgentExec1LogPo(agentExec1LogPo);
		return agentJobBindingDo;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void checkFinished(JobRunningDo jobRunningDo, ContextResponse response) {
		if (WebVariables.RESPONSE_SUCC_CODE.equals(response.getCode())
				|| WebVariables.RESPONSE_AGENT_EXCEPTION.equals(response.getCode())) {
			// 正常结束的
			JobUndoPlanPo jobUndoPlanPoLock = jobUndoPlanRepository.queryByIdWithLock(jobRunningDo.getJobLogId());
			if (jobUndoPlanPoLock == null) {
				// 待执行都没有了，任务肯定被处理掉了
				return;
			}
			jobUndoPlanRepository.deleteByIds(new Serializable[] { jobUndoPlanPoLock.getId() });

			JobExec1LogPo jobExec1LogPo = new JobExec1LogPo();
			jobExec1LogPo.setId(jobUndoPlanPoLock.getId());
			// jobExec1LogPo.setStartupTime(response.getStartDate());
			jobExec1LogPo.setEndTime(response.getEndDate());
			jobExec1LogPo.setExecStatus(response.getStatus());
			jobExec1LogPo.setExitCode(response.getExitValue());
			jobExec1LogPo.setExecResult(response.getMsg());
			jobExec1LogPo.setExecResultDetailed(response.getErrors());
			jobExec1LogRepository.updateById(jobExec1LogPo);

			if (WebVariables.RESPONSE_AGENT_EXCEPTION.equals(response.getCode())) {
				JobExec1LogPo jobExec1LogPoDb = jobExec1LogRepository.queryById(jobUndoPlanPoLock.getId());
				// 通知
				noticeHelper.recordNotice(jobExec1LogPoDb);
			}

			AgentExec1LogPo upAgentExec1Log = new AgentExec1LogPo();
			upAgentExec1Log.setId(jobRunningDo.getAgentId());
			upAgentExec1Log.setStartupTime(response.getStartDate());
			upAgentExec1Log.setEndTime(response.getEndDate());
			upAgentExec1Log.setExecResult(response.getMsg());
			upAgentExec1Log.setExecStatus(response.getStatus());
			agentExec1LogRepository.updateById(upAgentExec1Log);

		} else if (WebVariables.RESPONSE_AGENT_NOTFOUND.equals(response.getCode())) {
			// 执行器上没有找到任务记录，不确定了，可能删除，可能重启了
			// 按异常处理，，成败未知了
			JobUndoPlanPo jobUndoPlanPoLock = jobUndoPlanRepository.queryByIdWithLock(jobRunningDo.getJobLogId());
			if (jobUndoPlanPoLock == null) {
				// 待执行都没有了，任务肯定被处理掉了
				return;
			}
			jobUndoPlanRepository.deleteByIds(new Serializable[] { jobUndoPlanPoLock.getId() });

			JobExec1LogPo jobExec1LogPo = new JobExec1LogPo();
			jobExec1LogPo.setId(jobUndoPlanPoLock.getId());
			jobExec1LogPo.setExecStatus(ExecStatus.Excption.value());
			jobExec1LogPo.setExitCode(1);
			jobExec1LogPo.setEndTime(new Date());
			jobExec1LogPo.setExecResult(response.getMsg());
			jobExec1LogRepository.updateById(jobExec1LogPo);

			JobExec1LogPo jobExec1LogPoDb = jobExec1LogRepository.queryById(jobUndoPlanPoLock.getId());
			// 通知
			noticeHelper.recordNotice(jobExec1LogPoDb);

			AgentExec1LogPo upAgentExec1Log = new AgentExec1LogPo();
			upAgentExec1Log.setId(jobRunningDo.getAgentId());
			upAgentExec1Log.setStartupTime(response.getStartDate());
			upAgentExec1Log.setExecStatus(ExecStatus.Excption.value());
			upAgentExec1Log.setEndTime(new Date());
			upAgentExec1Log.setExecResult(response.getMsg());
			agentExec1LogRepository.updateById(upAgentExec1Log);

		} else if (WebVariables.RESPONSE_AGENT_UNKOWN.equals(response.getCode())) {
			// 未知状态，理论上程序还在执行中。。。
			System.out.println();
		}
	}

}
